import tkinter as tk
from tkinter import messagebox, ttk
from collections import defaultdict

# 初始化数据结构
books_catalog = []  # 图书目录
borrowed_books = []  # 学生借阅记录
student_credits = []  # 学生信用点
waitlist = []  # 预约系统
book_usage_stats = []  # 借阅统计
students = []  # 存储每个学生的借阅记录和信用分 [[name, borrowed_books, credits], ...]
current_student_index = 0  # 当前学生索引

current_student = "User1"  # 默认当前学生

books_catalog = [
    [1, "Introduction to Algorithms", "Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein", 2010, True],  # [ID, Title, Author, Year, Available]
    [2, "Python for Beginners", "Marie Dupont", 2022, True],
    [3, "Data Structures and Algorithms in Python","Michael T. Goodrich, Roberto Tamassia, Michael H. Goldwasser",2021,True],
    [4, "Databases: Concepts, Use and Development","Jean-Luc Hainaut",2020,True],
    [5, "Computer Networks","Andrew S. Tanenbaum, David J. Wetherall",2019,True],
]

# 添加新学生
def add_student(student_name):
    students.append([student_name, [], 3])  # 默认信用分为 3

# 切换当前学生并刷新界面
def switch_student(student_name):
    global current_student_index
    current_student_index = next(i for i, s in enumerate(students) if s[0] == student_name)
    refresh_ui()

# 刷新用户界面
def refresh_ui():
    current_student_data = students[current_student_index]
    borrowed_list = current_student_data[1]  # 借阅的书籍列表
    credits = current_student_data[2]  # 当前信用分
    
    credit_label.config(text=f"Current Credits: {credits}")
    
    borrowed_text = "\n".join(f"{book[1]} by {book[2]} ({book[3]})" for book in borrowed_list)
    
# 添加新书到图书馆目录
def add_new_book(title, author, year):
    new_id = len(books_catalog) + 1
    books_catalog.append([new_id, title, author, year, True])  # [ID, Title, Author, Year, Available]
    refresh_book_list(tree)
    messagebox.showinfo("Success", f"Book '{title}' added to the library with ID: {new_id}")

# 更新信用点显示
def update_credit_display():
    student_credit = next((c for c in student_credits if c[0] == current_student), None)
    if student_credit:
        credit_label.config(text=f"Current Credits: {student_credit[1]}")

# 报告丢失书籍并扣除信用点
def report_lost_book(book_id, tree):
    try:
        book_id = int(book_id)
        book = next((b for b in books_catalog if b[0] == book_id), None)
        if not book:
            messagebox.showerror("Error", "Book not found.")
            return
        
        student_credit = next((c for c in student_credits if c[0] == current_student), None)
        if not student_credit:
            student_credits.append([current_student, 3])  # 初始化信用点
            student_credit = student_credits[-1]
        
        if [current_student, book] in borrowed_books:
            if student_credit[1] <= 0:
                messagebox.showerror("Error", "You have no credits left to report lost books.")
                return
            
            # 扣除信用点
            student_credit[1] -= 1
            
            # 更新书籍状态
            borrowed_books.remove([current_student, book])
            books_catalog.remove(book)  # 从目录中移除丢失的书籍
            refresh_book_list(tree)
            
            # 更新信用点显示
            update_credit_display()

            # 显示剩余信用点
            messagebox.showinfo("Info", f"Book '{book[1]}' reported lost. Your remaining credits: {student_credit[1]}")
        else:
            messagebox.showerror("Error", "You did not borrow this book.")
    except ValueError:
        messagebox.showerror("Error", "Invalid book ID.")

# 搜索书籍
def search_books(query):
    results = [
        book for book in books_catalog
        if query.lower() in book[1].lower() 
        or query.lower() in book[2].lower() 
        or query == str(book[3])
    ]
    if not results:
        messagebox.showinfo("Search Results", "No books found.")
    else:
        result_text = "\n".join(f"{book[1]} by {book[2]} ({book[3]})" for book in results)
        messagebox.showinfo("Search Results", result_text)

# 查看书籍使用统计信息
def view_statistics():
    # 计算每本书的借阅次数
    stats = [(book[1], sum(1 for s in borrowed_books if s[1][1] == book[1])) for book in books_catalog]
    
    # 使用冒泡排序对书籍按借阅次数降序排列(buuble sort)
    n = len(stats)
    for i in range(n):
        for j in range(0, n - i - 1):
            if stats[j][1] < stats[j + 1][1]:  # 按借阅次数降序排序
                stats[j], stats[j + 1] = stats[j + 1], stats[j]

    # 构造显示文本
    stats_text = "\n".join(f"{title}: {count} times" for title, count in stats)
    messagebox.showinfo("Book Usage Statistics", f"Most Borrowed Books:\n\n{stats_text}")

# 刷新图书列表
def refresh_book_list(tree):
    tree.delete(*tree.get_children())
    for book in books_catalog:
        tree.insert("", "end", values=(book[0], book[1], book[2], book[3], "Yes" if book[4] else "No"))

# 借书
def borrow_book(book_id, tree):
    try:
        book_id = int(book_id)
        book = next((b for b in books_catalog if b[0] == book_id), None)
        if not book:
            messagebox.showerror("Error", "Book not found.")
            return
        
        student_credit = next((c for c in student_credits if c[0] == current_student), None)
        if not student_credit:
            student_credits.append([current_student, 3])  # 初始化信用点
            student_credit = student_credits[-1]
        
        if len([b for s, b in borrowed_books if s == current_student]) >= 7:
            messagebox.showerror("Error", "You have reached the maximum borrowing limit (7 books).")
            return
        if student_credit[1] <= 0:
            messagebox.showerror("Error", "You have no credits left to borrow books.")
            return
        
        # 更新书籍状态
        book[4] = False
        borrowed_books.append([current_student, book])
        refresh_book_list(tree)
        messagebox.showinfo("Success", f"You have borrowed '{book[1]}'.")

    except ValueError:
        messagebox.showerror("Error", "Invalid book ID.")

# 还书
def return_book(book_id, tree):
    try:
        book_id = int(book_id)
        book = next((b for b in books_catalog if b[0] == book_id), None)
        if not book:
            messagebox.showerror("Error", "Book not found.")
            return
        
        if [current_student, book] not in borrowed_books:
            messagebox.showerror("Error", "You did not borrow this book.")
            return
        
        # 更新书籍状态
        book[4] = True
        borrowed_books.remove([current_student, book])
        refresh_book_list(tree)
        messagebox.showinfo("Success", f"You have returned '{book[1]}'.")
        
        # 检查是否有等待列表
        wait_entry = next((w for w in waitlist if w[0] == book_id), None)
        if wait_entry and wait_entry[1]:
            next_student = wait_entry[1].pop(0)
            messagebox.showinfo("Reservation", f"The book has been reserved for {next_student}.")
            book[4] = False
            borrowed_books.append([next_student, book])
            refresh_book_list(tree)
    except ValueError:
        messagebox.showerror("Error", "Invalid book ID.")

# 预约书籍
def reserve_book(book_id):
    try:
        book_id = int(book_id)
        book = next((b for b in books_catalog if b[0] == book_id), None)
        if not book:
            messagebox.showerror("Error", "Book not found.")
            return
        
        if book[4]:
            messagebox.showinfo("Info", "The book is available now. You can borrow it directly.")
            return
        
        wait_entry = next((w for w in waitlist if w[0] == book_id), None)
        if not wait_entry:
            waitlist.append([book_id, []])
            wait_entry = waitlist[-1]
        
        if current_student in wait_entry[1]:
            messagebox.showinfo("Info", "You are already on the waitlist for this book.")
            return
        
        wait_entry[1].append(current_student)
        messagebox.showinfo("Success", f"You have joined the waitlist for '{book[1]}'.")
    except ValueError:
        messagebox.showerror("Error", "Invalid book ID.")


def main_window():
    root = tk.Tk()
    root.title("Library Management System")
    root.geometry("800x900")
    root.configure(bg='#f0f0f0')

    style = ttk.Style(root)
    style.theme_use('clam')  # 使用更现代的主题

    # 标题栏
    header_frame = tk.Frame(root, bg='#4CAF50', height=60)
    header_frame.pack(fill=tk.X)
    tk.Label(header_frame, text="Library Management System", font=("Arial", 20), bg='#4CAF50', fg='white').pack(pady=10)

    # 显示信用点
    credit_frame = tk.Frame(root, bg='#f0f0f0')
    credit_frame.pack(pady=5, fill=tk.X)
    global credit_label
    credit_label = tk.Label(credit_frame, text=f"Current Credits: {next((c[1] for c in student_credits if c[0] == current_student), 3)}", 
                            font=("Arial", 12), bg='#f0f0f0', fg='black')
    credit_label.pack()

    # 学生选择下拉菜单
    student_frame = tk.Frame(root, bg='#f0f0f0')
    student_frame.pack(pady=5, fill=tk.X)
    students_names = ["User1", "User2", "User3"]  # 示例学生名单
    selected_student = tk.StringVar(value=students_names[0])
    student_menu = ttk.Combobox(student_frame, textvariable=selected_student, values=students_names)
    student_menu.bind("<<ComboboxSelected>>", lambda e: switch_student(selected_student.get()))
    student_menu.pack(side=tk.LEFT, padx=10)
    
    # 显示图书列表
    tree_frame = tk.Frame(root, bg='#f0f0f0')
    tree_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    global tree
    tree = ttk.Treeview(tree_frame, columns=("ID", "Title", "Author", "Year", "Available"), show="headings", height=15)
    tree.heading("ID", text="ID", anchor=tk.W)
    tree.heading("Title", text="Title", anchor=tk.W) #text是表头文字，tk.w表示文字左对齐
    tree.heading("Author", text="Author", anchor=tk.W)
    tree.heading("Year", text="Year", anchor=tk.W)
    tree.heading("Available", text="Available", anchor=tk.W)
    tree.column("#1", stretch=tk.NO, width=50) #stretch: 是否允许列随窗口拉伸，width: 列的初始宽度
    tree.column("#2", stretch=tk.YES, minwidth=200)
    tree.column("#3", stretch=tk.YES, minwidth=150)
    tree.column("#4", stretch=tk.NO, width=70)
    tree.column("#5", stretch=tk.NO, width=100)
    tree.pack(fill=tk.BOTH, expand=True)

    refresh_book_list(tree)

    # 添加新书功能
    add_book_frame = tk.Frame(root, bg='#f0f0f0')
    add_book_frame.pack(pady=10, fill=tk.X)
    tk.Label(add_book_frame, text="Add Book:", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=0, padx=5)
    tk.Label(add_book_frame, text="Title", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=1, padx=5)
    title_entry = tk.Entry(add_book_frame, width=20, font=("Arial", 12))
    title_entry.grid(row=0, column=2, padx=5)
    tk.Label(add_book_frame, text="Author", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=3, padx=5)
    author_entry = tk.Entry(add_book_frame, width=20, font=("Arial", 12))
    author_entry.grid(row=0, column=4, padx=5)
    tk.Label(add_book_frame, text="Year", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=5, padx=5)
    year_entry = tk.Entry(add_book_frame, width=10, font=("Arial", 12))
    year_entry.grid(row=0, column=6, padx=5)
    add_button = tk.Button(add_book_frame, text="Add",
                           command=lambda: add_new_book(title_entry.get(), author_entry.get(), year_entry.get()),
                           font=("Arial", 12), bg='#4CAF50', fg='white')
    add_button.grid(row=0, column=7, padx=5)

    # 借书功能
    borrow_frame = tk.Frame(root, bg='#f0f0f0')
    borrow_frame.pack(pady=10, fill=tk.X)
    tk.Label(borrow_frame, text="Book ID to Borrow:", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=0, padx=5)
    borrow_id_entry = tk.Entry(borrow_frame, width=10, font=("Arial", 12))
    borrow_id_entry.grid(row=0, column=1, padx=5)
    borrow_button = tk.Button(borrow_frame, text="Borrow", command=lambda: borrow_book(borrow_id_entry.get(), tree),
                              font=("Arial", 12), bg='#4CAF50', fg='white')
    borrow_button.grid(row=0, column=2, padx=5)

    # 还书功能
    return_frame = tk.Frame(root, bg='#f0f0f0')
    return_frame.pack(pady=10, fill=tk.X)
    tk.Label(return_frame, text="Book ID to Return:", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=0, padx=5)
    return_id_entry = tk.Entry(return_frame, width=10, font=("Arial", 12))
    return_id_entry.grid(row=0, column=1, padx=5)
    return_button = tk.Button(return_frame, text="Return", command=lambda: return_book(return_id_entry.get(), tree),
                              font=("Arial", 12), bg='#FF5722', fg='white')
    return_button.grid(row=0, column=2, padx=5)

    # 报告丢失书籍功能
    lost_frame = tk.Frame(root, bg='#f0f0f0')
    lost_frame.pack(pady=10, fill=tk.X)
    tk.Label(lost_frame, text="Book ID Lost:", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=0, padx=5)
    lost_id_entry = tk.Entry(lost_frame, width=10, font=("Arial", 12))
    lost_id_entry.grid(row=0, column=1, padx=5)
    lost_button = tk.Button(lost_frame, text="Report Lost", command=lambda: report_lost_book(lost_id_entry.get(), tree),
                            font=("Arial", 12), bg='#FF5722', fg='white')
    lost_button.grid(row=0, column=2, padx=5)

    # 搜索功能
    search_frame = tk.Frame(root, bg='#f0f0f0')
    search_frame.pack(pady=10, fill=tk.X)
    tk.Label(search_frame, text="Search:", bg='#f0f0f0', font=("Arial", 12)).grid(row=0, column=0, padx=5)
    search_entry = tk.Entry(search_frame, width=30, font=("Arial", 12))
    search_entry.grid(row=0, column=1, padx=5)
    search_button = tk.Button(search_frame, text="Search", command=lambda: search_books(search_entry.get()),
                              font=("Arial", 12), bg='#4CAF50', fg='white')
    search_button.grid(row=0, column=2, padx=5)

    # 统计功能
    stats_button = tk.Button(root, text="View Statistics", command=view_statistics,
                             font=("Arial", 12), bg='#9C27B0', fg='white')
    stats_button.pack(pady=10)
    
    # 初始化学生信息
    for student in students_names:
        add_student(student)

    # 初始化界面
    switch_student(students_names[0])
    root.mainloop()


if __name__ == "__main__":
    main_window()